package com.jgp.attachment.controller;

import com.jgp.attachment.exception.DocException;
import com.jgp.attachment.model.FileInfo;
import com.jgp.attachment.service.DocService;
import com.jgp.sys.controller.JGPBackController;
import com.jgp.sys.ui.Result;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.*;

/**
 * 项目   parent
 * 作者   loufei
 * 时间   2018/4/25
 */
@Log4j2
@RestController
@RequestMapping("/attachment/docApiController")
public class DocApiController extends JGPBackController {
    
    @Autowired
    private DocService docService;
    
    @PostMapping(value = "upload")
    public Result upload(@RequestPart("file") MultipartFile file, HttpServletRequest request) throws DocException {
        Result result = new Result(true);
        FileInfo fileInfo = docService.upload(file, request);
        
        if (Objects.nonNull(fileInfo)) {
            result.addData("fileId", fileInfo.getId());
        }
        return result;
    }
    
    @PostMapping(value = "upload-mobile")
    public Result uploadMobile(@RequestPart("file") MultipartFile file, HttpServletRequest request) throws DocException {
        
        Result result = new Result(true);
        FileInfo fileInfo = docService.upload(file, request);
        if (Objects.nonNull(fileInfo)) {
            result.addData("fileId", fileInfo.getId());
        }
        return result;
    }
    
    @PostMapping(value = "uploadEditorImage")
    public Map uploadEditorImage(@RequestParam MultipartFile file, HttpServletRequest request) throws DocException {
        FileInfo fileInfo = docService.uploadEditorImage(file, request);
        Map<String, Object> result = new HashMap<>();
        result.put("error", false);
        result.put("location", fileInfo.getPath());
        return result;
    }
    
    
    /**
     * md5验证文件是否存在
     *
     * @param md5
     * @return
     */
    @PostMapping(value = "md5Check/{md5}")
    public Result md5Check(@PathVariable("md5") String md5) {
        FileInfo fileInfo = docService.queryByMd5(md5);
        if (Objects.nonNull(fileInfo)) {
            return ajaxReData("fileId", fileInfo.getId());
        }
        return ajaxRe(false);
    }
    
    /**
     * 查询挂载对象下的所有文件
     *
     * @param objectId   挂载对象id
     * @param objectType 挂载对象类型
     * @return 文件集合
     */
    @RequestMapping(value = {"queryFileByObject", "query-file-by-object"}, method = {RequestMethod.GET, RequestMethod.POST})
    public Result queryFiles(String objectId, String objectType) {
        List<FileInfo> files = docService.queryFiles(objectId, objectType);
        return ajaxReData("files", files);
    }
    
    @RequestMapping(value = "queryFileByFileIds", method = {RequestMethod.GET, RequestMethod.POST})
    public Result queryFiles(String[] fileIds) {
        List<FileInfo> files = docService.queryFiles(Arrays.asList(fileIds));
        return ajaxReData("files", files);
    }
    
    @PostMapping("updateMountInfo")
    public Result updateMountInfo(String objectId, String objectType, String[] fileIds) {
        try {
            docService.mountFilesToObject(objectId, objectType, fileIds);
            return ajaxRe(true);
        } catch (Exception e) {
            return ajaxRe(false);
        }
    }
    
    
    @RequestMapping(value = {"viewDoc/{fileId}", "view-doc/{fileId}", "view-doc/{fileId}.pdf"}, method = {RequestMethod.GET, RequestMethod.POST},
            produces = {MediaType.IMAGE_PNG_VALUE, MediaType.IMAGE_GIF_VALUE, MediaType.IMAGE_JPEG_VALUE, MediaType.APPLICATION_PDF_VALUE})
    public ResponseEntity<?> viewDoc(@PathVariable("fileId") String fileId) throws IOException {
        FileInfo fileInfo = docService.queryFile(fileId);
        HttpHeaders headers = new HttpHeaders();
        String[] types = fileInfo.getMimeType().split("/");
        headers.setContentType(new MediaType(types[0], types[1], Charset.forName("utf-8")));
        headers.setContentDisposition(ContentDisposition.builder("inline").filename(fileInfo.getName()).build());
        return ResponseEntity.ok().headers(headers).body(IOUtils.toByteArray(new FileSystemResource(fileInfo.getDiskPath()).getInputStream()));
    }
    
    @ApiOperation("根据尺寸获取图片")
    @RequestMapping(value = {"viewPic/{fileId}/{size}", "view-pic/{fileId}/{size}"}, method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<?> viewThumbPic(@PathVariable("fileId") String fileId, @PathVariable("size") String size) {
        ResponseEntity<?> entity = viewPicEntity(docService.queryFile(fileId), size);
        if(Objects.isNull(entity)){
            log.warn("找不到文件 fileId:"+fileId);
        }
        return entity;
    }
    
    @RequestMapping(value = "viewPicWater/{fileId}", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<?> viewPicWater(@PathVariable("fileId") String fileId) {
        ResponseEntity<?> entity = viewPicEntity(docService.queryFile(fileId), "water");
        if(Objects.isNull(entity)){
            log.warn("找不到文件 fileId:"+fileId);
        }
        return entity;
    }
    
    @RequestMapping(value = {"viewPicOriginal/{fileId}", "view-pic-original/{fileId}"}, method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<?> viewPicOriginal(@PathVariable("fileId") String fileId) {
        ResponseEntity<?> entity = viewPicEntity(docService.queryFile(fileId), "original");
        if(Objects.isNull(entity)){
            log.warn("找不到文件 fileId:"+fileId);
        }
        return entity;
    }
    
    private ResponseEntity<?> viewPicEntity(FileInfo fileInfo, String size) {
        if(Objects.isNull(fileInfo)){
            return null;
        }
        String path = fileInfo.getDiskDir() + "/thumb_" + size + "_" + fileInfo.getDiskName();
        HttpHeaders headers = new HttpHeaders();
        if ("original".equals(size)) {
            path = fileInfo.getDiskPath();
        } else if ("water".equals(size)) {
            path = fileInfo.getDiskDir() + "/water_" + fileInfo.getDiskName();
        }
        String[] types = fileInfo.getMimeType().split("/");
        headers.setContentType(new MediaType(types[0], types[1], Charset.forName("utf-8")));
        
        try {
            return ResponseEntity.ok().headers(headers).body(new FileSystemResource(path));
        } catch (Exception e) {
            return ResponseEntity.notFound().build();
        }
        
        
    }
    
    @GetMapping(value = "download/{fileId}")
    public ResponseEntity<FileSystemResource> download(@PathVariable("fileId") String fileId) throws UnsupportedEncodingException {
        return downloadEntity(docService.queryFile(fileId));
    }
    
    @GetMapping(value = "download/{fileId}.{ext}")
    public ResponseEntity<FileSystemResource> downloadWithExt(@PathVariable("fileId") String fileId, @PathVariable("ext") String ext
    ) throws UnsupportedEncodingException {
        return downloadEntity(docService.queryFile(fileId));
    }
    
    private ResponseEntity<FileSystemResource> downloadEntity(FileInfo fileInfo) throws UnsupportedEncodingException {
        if (fileInfo == null) {
            return null;
        }
        
        File file = new File(fileInfo.getDiskPath());
        
        if (!file.exists()) {
            return null;
        }
        
        HttpHeaders headers = new HttpHeaders();
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        headers.add("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileInfo.getName(), "UTF-8"));
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");
        
        return ResponseEntity.ok().headers(headers).contentLength(file.length()).contentType(MediaType.parseMediaType(fileInfo.getMimeType()))
                             .body(new FileSystemResource(fileInfo.getDiskPath()));
    }
    
    @RequestMapping(value = {"remove/{objectId}/{objectType}/{fileId}", "remove-file/{objectId}/{objectType}/{fileId}"},
            method = {RequestMethod.GET, RequestMethod.POST})
    public Result remove(
            @PathVariable("objectId") String objectId, @PathVariable("objectType") String objectType, @PathVariable("fileId") String fileId
    ) {
        docService.removeFile(objectId, objectType, fileId);
        return ajaxRe(true);
    }
    
}
